/*
 *  SoundPlayer.h
 *  SoundEngine
 *
 *   Created by jobs mac on 09-5-7.
 *   Copyright __MyCompanyName__ 2009. All rights reserved.
 *
 */
#import <OpenAL/al.h>
#import <OpenAL/alc.h>
#import <string>
#import <map>
#import "SoundInfo.h"
#import "Mutex.h"

//	听者音量
#define kMin_Volume_Listener		0.0f
#define	kMax_Volume_Listener		4.0f

//	源音量
#define kMin_Volume_Source			0.0f
#define	kMax_Volume_Source			1.0f

#ifndef kPlayerUseThread
//	#define kPlayerUseThread
#endif

typedef std::map<std::string, CSoundBase*> mapStrToSound;

class CSoundPlayer  {
private:
	CSoundPlayer();
	CSoundPlayer(const CSoundPlayer &other);
	CSoundPlayer& operator=(const CSoundPlayer &other);
	virtual ~CSoundPlayer();
public:	
	
	
	enum {
		SOUND_STATE_UNKNOWN = 0,
		SOUND_STATE_INITIAL = AL_INITIAL,
		SOUND_STATE_PLAYING = AL_PLAYING,
		SOUND_STATE_STOPPED = AL_STOPPED,
		SOUND_STATE_PAUSED  = AL_PAUSED,
	};
	
	enum {
		SOUND_UPDATE_THREAD_RUNING = 0,
		SOUND_UPDATE_THREAD_STOPING,
		SOUND_UPDATE_THREAD_STOPPED,
	};
	
private:
	int _InitAudioSession();
	int _InitOpenAL();
	void _InterruptArise();
	void _InterruptLeave();
	
	static void AudioSessionISP(void * inClientData, UInt32 inInterruptionState);
	
	//	初始化播放器
	int InitPlayer();
	
public:
	

	
	//	添加音乐
	int soundAdd(const char *szFileName, bool bQueue = false)
	{
		assert(NULL != szFileName);
		if ( NULL == szFileName )
		{
			return 0;
		}

#ifdef kPlayerUseThread		
		printf("Add()--Lock begin\n");
		CMutex mutex(&m_MutexSound);
		printf("Add()--Lock end\n");
#endif
		
		std::string szName(szFileName);
		mapStrToSound::iterator it = m_mapStrToSound.find(szName);
		if ( it != m_mapStrToSound.end() )
		{	//	音乐已经存在
			return 1;
		}
		
		CSoundBase *pSound = CSoundBase::CreateSound(szFileName, bQueue);
		if ( NULL != pSound )
		{	
			m_mapStrToSound[szName] = pSound;
			
			return 1;
		}
		
		return 0;
	}
	
	//	删除音乐
	int soundRemove(const char *szFileName)
	{
		assert(NULL != szFileName);
		if ( NULL == szFileName )
		{
			return 0;
		}
		
#ifdef kPlayerUseThread		
		printf("Remove()--Lock begin\n");
		CMutex mutex(&m_MutexSound);
		printf("Remove()--Lock end\n");
#endif		
		std::string szName(szFileName);
		mapStrToSound::iterator it = m_mapStrToSound.find(szName);
		if ( it == m_mapStrToSound.end() )
		{
			return 0;
		}
		
		CSoundBase *pSound = it->second;
		pSound->Release();
		delete pSound;
		
		m_mapStrToSound.erase(it);
		
		return 1;
	}
	
	//	删除所有音乐
	int soundClear()
	{
		int i4Ret = 1;
#ifdef kPlayerUseThread		
		printf("Clear()--Lock begin\n");
		CMutex mutex(&m_MutexSound);
		printf("Clear()--Lock end\n");
#endif		
		mapStrToSound::iterator it = m_mapStrToSound.begin();
		while ( it != m_mapStrToSound.end() ) {
			if ( !soundRemove(it->first.c_str()) )
			{
				i4Ret = 0;
			}
			
			it = m_mapStrToSound.begin();
		}
		return i4Ret;
	}
	
	//	播放
	int soundPlay(const char *szFileName, bool bLooping = false)
	{
		assert(NULL != szFileName);
		if ( NULL == szFileName )
		{
			return 0;
		}
#ifdef kPlayerUseThread		
		printf("Play()--Lock begin\n");
		CMutex mutex(&m_MutexSound);
		printf("Play()--Lock end\n");
#endif		
		std::string szName(szFileName);
		mapStrToSound::iterator it = m_mapStrToSound.find(szName);
		if ( it == m_mapStrToSound.end() )
		{
			return 0;
		}
		
		it->second->Play(bLooping);
		
		return 1;
	}
	//	停止
	int soundStop(const char *szFileName)
	{
		assert(NULL != szFileName);
		if ( NULL == szFileName )
		{
			return 0;
		}
#ifdef kPlayerUseThread		
		printf("Stop()--Lock begin\n");
		CMutex mutex(&m_MutexSound);
		printf("Stop()--Lock end\n");
#endif		
		std::string szName(szFileName);
		mapStrToSound::iterator it = m_mapStrToSound.find(szName);
		if ( it == m_mapStrToSound.end() )
		{
			return 0;
		}
		
		it->second->Stop();
		return 1;
	}
	//	暂停
	int soundPause(const char *szFileName)
	{
		assert(NULL != szFileName);
		if ( NULL == szFileName )
		{
			return 0;
		}
#ifdef kPlayerUseThread		
		printf("Pause()--Lock begin\n");
		CMutex mutex(&m_MutexSound);
		printf("Pause()--Lock end\n");
#endif		
		std::string szName(szFileName);
		mapStrToSound::iterator it = m_mapStrToSound.find(szName);
		if ( it == m_mapStrToSound.end() )
		{
			return 0;
		}
		
		it->second->Pause();
		return 1;
	}
	
	//	停止所有音乐
	int soundStopAll()
	{
		int i4Ret = 1;
#ifdef kPlayerUseThread		
		printf("StopAll()--Lock begin\n");
		CMutex mutex(&m_MutexSound);
		printf("StopAll()--Lock end\n");
#endif		
		mapStrToSound::iterator it = m_mapStrToSound.begin();
		mapStrToSound::iterator itEnd = m_mapStrToSound.end();
		while (it != itEnd) {
			if ( !soundStop(it->first.c_str()) )
			{
				i4Ret = 0;
			}
			++it;
		}
		return i4Ret;
	}
	
	//	获取播放状态
	int soundState(const char *szFileName, int &i4SoundState)
	{
		assert(NULL != szFileName);
		if ( NULL == szFileName )
		{
			return 0;
		}
#ifdef kPlayerUseThread		
		printf("State()--Lock begin\n");
		CMutex mutex(&m_MutexSound);
		printf("State()--Lock end\n");
#endif		
		std::string szName(szFileName);
		mapStrToSound::iterator it = m_mapStrToSound.find(szName);
		if ( it == m_mapStrToSound.end() )
		{
			i4SoundState = SOUND_STATE_UNKNOWN;
			return 0;
		}
		
		i4SoundState = it->second->State();
		return 1;
	}
	
	//	设置音量, szFileName == NULL, 设置听者音量，影响所有源；否则设置源音量，影响一个源
	int soundVolume(const char *szFileName, float fVolume)
	{
		if ( NULL == szFileName ) 
		{
			if ( kMin_Volume_Listener > fVolume ) 
				fVolume = kMin_Volume_Listener;
			else if (kMax_Volume_Listener < fVolume ) 
				fVolume = kMax_Volume_Listener;
			alListenerf(AL_GAIN, fVolume);			
		}
		else
		{
			if ( kMin_Volume_Source > fVolume ) 
				fVolume = kMin_Volume_Source;
			else if (kMax_Volume_Listener < fVolume ) 
				fVolume = kMax_Volume_Source;
#ifdef kPlayerUseThread			
			printf("Volume()--Lock begin\n");
			CMutex mutex(&m_MutexSound);
			printf("Volume()--Lock end\n");
#endif			
			std::string szName(szFileName);
			mapStrToSound::iterator it = m_mapStrToSound.find(szName);
			if ( it == m_mapStrToSound.end() )
			{
				return 0;
			}
			
			it->second->SetVolume(fVolume);
		}
		return 1;
	}

#ifndef kPlayerUseThread	
	int soundUpdate(float dt)
	{
		return Update(dt);
	}
#endif
	
	void Release()
	{
		if (--m_i4CountRef <= 0)
		{
			m_pThis = NULL;
			delete this;
		}
	}
	
	static CSoundPlayer* GetInstance();
	
private:
	mapStrToSound			m_mapStrToSound;
	static CSoundPlayer		*m_pThis;
	static pthread_mutex_t	m_MutexClass;
	static pthread_mutex_t	m_MutexSound;
	
	int						m_i4CountRef;
	
	int						m_i4ThreadState;
	int						m_priority;
	
	pthread_t				m_thread;
	unsigned int			m_thread_hdl;
	
	static void* UpdateThread(void* pVoid);
	
	//	更新播放队列，用于以队列方式播放的音乐
	int Update(float dt)
	{
#ifdef kPlayerUseThread		
		//printf("Update()--Lock begin\n");
		CMutex mutex(&m_MutexSound);
		//printf("Update()--Lock end\n");
#endif		
		mapStrToSound::iterator it = m_mapStrToSound.begin();
		mapStrToSound::iterator itEnd = m_mapStrToSound.end();
		while (it != itEnd) {
			it->second->Update(dt);
			++it;
		}
		return 1;
	}
};